﻿/*
   Copyright 2011 Softisis

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/



using System;
using FOM.Interfaces;

namespace FOM.Impl
{
    /// <summary>
    /// Goto implementation of a mapping. A GoTo is a way to point at a sub path, without repeating the root path.
    /// It's look like mapping in the way of using it, but it doe not create a mapping.
    /// Example: Map(s=>s.foo.bar.urg.x, d=>d.alpha.beta.y) is equivalent to
    /// GoTo(s=>s.foo.bar.urg, d=>d.alpha.beta).Map(s=>s.x, d=>d.y).
    /// Consequently, some operations are not allowed: newInstance() and UseConververt().
    /// </summary>
    /// <remarks>Copyright Softisis 2011 (France)</remarks>
    /// <typeparam name="TSrc">Type of the source object</typeparam>
    /// <typeparam name="TDst">Type of the destination object</typeparam>
    public class GoToMappingNodeImpl<TSrc, TDst> : MappingNodeImpl<TSrc, TDst>
    {
        public GoToMappingNodeImpl(string srcpath, string dstpath) : base(srcpath, dstpath)
        {
        }

        public override IMappingNode<TSrc, TDst> NewInstance()
        {
            throw new Exception("New instance can't be called on a GoTo operation, because goto operation do not generate/manage an instance. Only on a mapping.");
        }


        public override IMappingNode<TSrc, TDst> UseConverter(IConverter converter)
        {
            throw new Exception("UseConverter can't be called on a GoTo operation, because goto operation do not generate/manage an instance. Only on a mapping.");
        }

        public override IMappingNode<TSrc, TDst> UseCondition(ICondition  converter)
        {
            throw new Exception("UseCondition can't be called on a GoTo operation, because goto operation do not generate/manage an instance. Only on a mapping.");
        }

        internal override MappingNodeImpl<TDst, TSrc> GetInstance()
        {
            return new GoToMappingNodeImpl<TDst, TSrc>(NodePathLink.TargetPath, NodePathLink.SourcePath);
        }

        public override AbstractMappingNode ReverseNode()
        {
            var newone = GetInstance();
            newone.TargetOverrideType = SourceOverrideType;
            newone.SourceOverrideType = TargetOverrideType;
            newone.NodePathLink = NodePathLink == null ? null : NodePathLink.Reverse();

            if (Excluded != null)
                foreach (var pl in Excluded)
                    newone.Excluded.Add(pl.Reverse());

            if (Children != null)
                foreach (var c in Children)
                    newone.AddMapping(c.ReverseNode());
            return newone;
        }
    }
}
